package com.bupt.uchouten.client.render.block.entity;

import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.joml.Quaternionf;

public abstract class AbstractBlockEntityRenderer<T extends BlockEntity> implements BlockEntityRenderer<T> {
    boolean flip = true;
    float scale = 0.0F;
    float yOffset = 0.0F;
    int correctionAngles = 0;
    boolean doProcessing = true;

    public AbstractBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
    }

    @Override
    public void render(T te, float partialTicks, PoseStack matrix, MultiBufferSource buffer, int combinedLight, int combinedOverlay) {
        if (this.doProcessing) {
            int rotateDegrees = this.getRotation(te == null ? null : te.getBlockState());
            matrix.pushPose();
            matrix.translate(0.5F, this.yOffset, 0.5F);
            matrix.mulPose(fromEuler((float)(rotateDegrees + this.correctionAngles), 0.0F, 1.0F, 0.0F));
            if (this.flip) {
                matrix.mulPose(fromEuler(180.0F, 0.0F, 0.0F, 1.0F));
            }

            if (this.scale != 0.0F) {
                matrix.scale(this.scale, this.scale, this.scale);
            }
        }

        this.render(te, te == null ? null : te.getBlockState(), te == null ? 0.0 : (double)te.getBlockPos().getX(), te == null ? 0.0 : (double)te.getBlockPos().getY(), te == null ? 0.0 : (double)te.getBlockPos().getZ(), partialTicks, matrix, buffer, combinedLight, combinedOverlay);
        if (this.doProcessing) {
            matrix.popPose();
        }

    }

    public abstract void render(T var1, BlockState var2, double var3, double var5, double var7, float var9, PoseStack var10, MultiBufferSource var11, int var12, int var13);

    protected abstract int getRotation(BlockState state);

    public static Quaternionf fromEuler(float deg, float x, float y, float z) {
        double xValue = (double)(deg * x) * 0.017453292519943295;
        double yValue = (double)(deg * y) * 0.017453292519943295;
        double zValue = (double)(deg * z) * 0.017453292519943295;
        float f = Mth.sin((float)(0.5 * xValue));
        float f1 = Mth.cos((float)(0.5 * xValue));
        float f2 = Mth.sin((float)(0.5 * yValue));
        float f3 = Mth.cos((float)(0.5 * yValue));
        float f4 = Mth.sin((float)(0.5 * zValue));
        float f5 = Mth.cos((float)(0.5 * zValue));
        return new Quaternionf(f * f3 * f5 + f1 * f2 * f4, f1 * f2 * f5 - f * f3 * f4, f * f2 * f5 + f1 * f3 * f4, f1 * f3 * f5 - f * f2 * f4);
    }
}
